/* Includes ------------------------------------------------------------------*/
#include "PWM.h"
#include "Led7Seg.h"
#include "SystemTick.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/
#define FREQ_MAX        500
#define FREQ_NORMAL     400
#define FREQ_MIN        300

#define TIME_TURN_ON    30      /* 30x100ms = 3s */
#define TIME_TURN_OFF   20      /* 20x100ms = 2s */


u16         s_CurFreq = FREQ_NORMAL;
e_PWM_MODE  s_Mode = MODE_CONTINUOUS;
u16         s_ModeCnt = 0;

void PWM_SetFreq(u16 iFreq);


void PWM_Init(void)
{
    PWM_SetFreq(s_CurFreq);
}


void PWM_Disable(void)
{
    TIM2_Cmd(DISABLE);
    TIM2_DeInit();
}


void PWM_Enable(void)
{
    u16 period = (160000/(s_CurFreq+5));

    /* TIM2 Peripheral Configuration */ 
    TIM2_Cmd(DISABLE);
    TIM2_DeInit();

    /* Set TIM2 Frequency Master to 16Mhz */ 
    TIM2_TimeBaseInit(TIM2_PRESCALER_1, (period-2));


    /* Channel 1 PWM configuration */ 
    TIM2_OC1Init(TIM2_OCMODE_PWM2, TIM2_OUTPUTSTATE_ENABLE,(period>>1), TIM2_OCPOLARITY_LOW ); 
    TIM2_OC1PreloadConfig(ENABLE);

    /* Enables TIM2 peripheral Preload register on ARR */
    TIM2_ARRPreloadConfig(ENABLE);

    /* Enable TIM2 */
    TIM2_Cmd(ENABLE);
}


void PWM_SetFreq(u16 iFreq)
{
    u16 period = (160000/(iFreq+5));

    /* TIM2 Peripheral Configuration */ 
    TIM2_Cmd(DISABLE);
    TIM2_DeInit();

    /* Set TIM2 Frequency Master to 16Mhz */ 
    TIM2_TimeBaseInit(TIM2_PRESCALER_1, (period-2));


    /* Channel 1 PWM configuration */ 
    TIM2_OC1Init(TIM2_OCMODE_PWM2, TIM2_OUTPUTSTATE_ENABLE,(period>>1), TIM2_OCPOLARITY_LOW ); 
    TIM2_OC1PreloadConfig(ENABLE);

    /* Enables TIM2 peripheral Preload register on ARR */
    TIM2_ARRPreloadConfig(ENABLE);

    /* Enable TIM2 */
    TIM2_Cmd(ENABLE);

    Led7Seg_Push(iFreq);
}

void PWM_ChangeMode(void)
{
    if (MODE_CONTINUOUS == s_Mode)
    {
        s_Mode = MODE_ON;
        s_ModeCnt = 0;
    }
    else
    {
        s_Mode = MODE_CONTINUOUS;
    }

    PWM_SetFreq(s_CurFreq);
    Led7Seg_SetDispDp(TRUE);
}


void PWM_IncFreq(void)
{
    if (FREQ_MAX > s_CurFreq)
    {
        s_CurFreq += 5;
        if (MODE_CONTINUOUS != s_Mode)
        {
            s_Mode = MODE_ON;
            s_ModeCnt = 0;
        }
        PWM_SetFreq(s_CurFreq);
    }
}


void PWM_DecFreq(void)
{
    if (FREQ_MIN < s_CurFreq)
    {
        s_CurFreq -= 5;
        if (MODE_CONTINUOUS != s_Mode)
        {
            s_Mode = MODE_ON;
            s_ModeCnt = 0;
        }
        PWM_SetFreq(s_CurFreq);
    }
}


void PWM_RunOne(void)
{
    // s_PWM_IntFlag = TRUE moi 100ms/lan
    if (TRUE == s_PWM_IntFlag)
    {
        s_PWM_IntFlag = FALSE;

        if (MODE_CONTINUOUS != s_Mode)
        {
            switch (s_Mode)
            {
            case MODE_ON:
                {
                    if (TIME_TURN_ON <= ++s_ModeCnt)
                    {
                        s_ModeCnt = 0;
                        PWM_Disable();
                        Led7Seg_Push(0);
                        s_Mode = MODE_OFF;
                    }
                } break;

            case MODE_OFF:
                {
                    if (TIME_TURN_OFF <= ++s_ModeCnt)
                    {
                        s_ModeCnt = 0;
                        PWM_Enable();
                        Led7Seg_Push(s_CurFreq);
                        s_Mode = MODE_ON;
                    }
                } break;
            }

            if (TRUE == Led7Seg_GetDispDp())
            {
                Led7Seg_SetDispDp(FALSE);
            }
            else
            {
                Led7Seg_SetDispDp(TRUE);
            }
        }
    }
}
